/**
 * Copyright 2015-2016 eyaomall.cn
 * All rights reserved.
 *
 * @project
 * @author jackey
 * @version 1.0
 * @date 2016-01-06
 */
package com.eyaomall.wxmall.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.eyaomall.wxmall.common.enums.MemberCookieEnums;
import com.eyaomall.wxmall.common.helper.MemberHelper;
import com.eyaomall.wxmall.common.util.WChatUtil;
import com.eyaomall.wxmall.model.po.Member;
import com.eyaomall.wxmall.model.po.Shop;
import com.eyaomall.wxmall.model.pojo.ResAccessToken;
import com.eyaomall.wxmall.model.pojo.ResWxUser;
import com.eyaomall.wxmall.model.vo.ShopExtVO;
import com.eyaomall.wxmall.service.AdvertPlaceService;
import com.eyaomall.wxmall.service.AdvertService;
import com.eyaomall.wxmall.service.MemberService;
import com.eyaomall.wxmall.service.ShopExtService;
import com.eyaomall.wxmall.service.ShopService;
import com.github.pagehelper.StringUtil;
import com.lycheeframework.core.cmp.api.error.SECode;
import com.lycheeframework.core.cmp.api.http.GsnData;
import com.lycheeframework.core.cmp.api.http.GsnResponse;
import com.lycheeframework.core.common.cookie.SessionManager;
import com.lycheeframework.core.common.helper.GlobEnv;
import com.lycheeframework.core.common.util.JSONUtil;
import com.lycheeframework.core.exception.ErrorCodeException;

/**
 * 首页
 * 
 * @author pro
 *
 */
@Controller
@RequestMapping("/")
public class HomeController {

	private static Logger LOG = org.slf4j.LoggerFactory.getLogger(HomeController.class);

	@Autowired
	private MemberService memberService;

	@Autowired
	private ShopService shopService;

	@Autowired
	private ShopExtService shopExtService;

	@Autowired
	private AdvertService advertService;

	@Autowired
	private AdvertPlaceService advertPlaceService;

	/**
	 * 跳转至首页
	 * 
	 * @param data
	 * @return
	 */
	@RequestMapping("verify")
	public String index(Integer shopId, String redirect, Map<String, Object> data, HttpServletRequest request) {
		Shop shop = shopService.queryById(shopId);
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + shop.getWxAppId()
				+ "&redirect_uri=";
		try {
			if (StringUtil.isNotEmpty(redirect)) {
				redirect = URLEncoder.encode(redirect, "utf-8");
			} else {
				redirect = "";
			}

			url += URLEncoder.encode(GlobEnv.get("verify.url") + "access_token?appId=" + shop.getWxAppId()
					+ "&appSecert=" + shop.getWxSecretKey() + "&redirect=" + redirect, "utf-8");
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
		url += "&response_type=code&scope=snsapi_userinfo&state=" + shopId + "#wechat_redirect";

		return "redirect:" + url;
	}

	/**
	 * 获取accessToken
	 * 
	 * @param code
	 * @return
	 */
	@RequestMapping("access_token")
	public String accessToken(String code, String state, String redirect, String appId, String appSecert,
			HttpServletRequest request, HttpServletResponse response) {
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecert
				+ "&code=" + code + "&grant_type=authorization_code";
		ResAccessToken accessToken = WChatUtil.getUser(url);
		if (accessToken == null)
			throw new ErrorCodeException(SECode.s_100000);

		return "redirect:" + GlobEnv.getWebURL("") + "?openId=" + accessToken.getOpenid() + "&shopId=" + state
				+ "&accessToken=" + accessToken.getAccess_token() + "&redirect=" + redirect;

	}

	/**
	 * 主页面
	 * 
	 * @return
	 */
	@RequestMapping("")
	public String main(String openId, Integer shopId, String redirect, String accessToken, Map<String, Object> data,
			HttpServletRequest request, HttpServletResponse response) {
		Shop shop = null;
		if (shopId != null && shopId > 0) {
			shop = shopService.queryShop(shopId);
		} else {
			shop = shopService.queryShop(MemberHelper.getShopId());
		}
		if (StringUtil.isEmpty(openId) || shopId == null || shopId <= 0 || StringUtil.isEmpty(accessToken)) {
			data.put("nickname", MemberHelper.getNickName());
			data.put("shopInfo", shop);
			data.put("advert", advertService.listPage());
			
			if (shop.getParentId() != 0) {
				ShopExtVO sev = shopExtService.getParent(shop.getParentId());
				if (sev != null && sev.getAdvertisingLink().indexOf("www") != -1) {
					sev.setLinkType("url");
				}
				data.put("parent", sev);
			}
			return "home/index";
		}

		LOG.error("openId:" + openId);
		if (StringUtil.isNotEmpty(accessToken) && StringUtil.isNotEmpty(openId)) {
			data.put("accessToken", accessToken);
			data.put("openId", openId);
			data.put("shopId", shopId);

			ResWxUser wxUser = WChatUtil.getAccessToken(accessToken, openId);
			Member member = memberService.queryById(openId, shopId);
			SessionManager manager = new SessionManager(request);
			// 清除缓存
			if (member == null) {
				member = new Member();
				member.setWxOpenId(openId);
				if (wxUser != null) {
					member.setWxName(wxUser.getNickname());
				}

				member.setShopId(shopId);
				Integer memberId = memberService.create(member);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(),MemberCookieEnums._MALL_FORM_MEMBER_ID.getName(), String.valueOf(memberId), true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(), MemberCookieEnums._MALL_FORM_OPEN_ID.getName(),openId, true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(), MemberCookieEnums._MALL_FORM_SHOP_ID.getName(),String.valueOf(shopId), true);
			} else {
				if (wxUser != null) {
					member.setWxName(wxUser.getNickname());
					memberService.update(member);
				}

				LOG.error("update :shopId" + shopId + "memberId：" + member.getId());
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(),MemberCookieEnums._MALL_FORM_MEMBER_ID.getName(), String.valueOf(member.getId()), true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(), MemberCookieEnums._MALL_FORM_OPEN_ID.getName(),openId, true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(), MemberCookieEnums._MALL_FORM_SHOP_ID.getName(),String.valueOf(shopId), true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(), MemberCookieEnums._MALL_FORM_PHONE.getName(),member.getPhone(), true);
			}

			if (wxUser != null) {
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(),MemberCookieEnums._MALL_FORM_HEAD_IMG.getName(), wxUser.getHeadimgurl(), true);
				manager.setValue(MemberCookieEnums._MALL_FORM.getName(),MemberCookieEnums._MALL_FORM_NICK_NAME.getName(), wxUser.getNickname(), true);
			}
			manager.save(request, MemberCookieEnums._MALL_FORM.getName(), true);
		}

		data.put("shopInfo", shop);
		data.put("nickname", MemberHelper.getNickName());
		data.put("advert", advertService.listPage());
		
		if (shop.getParentId() != 0) {
			ShopExtVO sev = shopExtService.getParent(shop.getParentId());
			if (sev != null && sev.getAdvertisingLink() != null && sev.getAdvertisingLink().indexOf("www") > 0) {
				sev.setLinkType("url");
			}
			data.put("parent", sev);
		}
		if (StringUtil.isNotEmpty(redirect) && !"null".equals(redirect)) {
			return "redirect:" + redirect;
		}

		return "home/index";
	}

	/**
	 * 微信分享示例
	 * 
	 * @return
	 */
	@RequestMapping("share")
	public String share(Integer shopId, Map<String, String> data, HttpServletRequest request) {
		StringBuffer url = request.getRequestURL();
		String queryStr = request.getQueryString();
		if (StringUtil.isNotEmpty(queryStr)) {
			url.append("?");
			url.append(queryStr);
		}
		data.put("memberId", String.valueOf(MemberHelper.getId()));

		return "home/share";
	}

	/**
	 * 获取微信公众号js签名
	 * 
	 * @param openId
	 * @param url
	 * @param token
	 * @return
	 */
	@RequestMapping("create_sign")
	public @ResponseBody GsnData createSign(String url) {
		Integer shopId = MemberHelper.getShopId();
		Shop shop = shopService.queryById(shopId);

		Map<String, String> sign = sign(shop.getJsTicket(), url);
		sign.put("appId", shop.getWxAppId());
		return GsnResponse.toData(sign);
	}

	public static Map<String, String> sign(String jsapi_ticket, String url) {
		Map<String, String> ret = new HashMap<String, String>();
		String nonce_str = create_nonce_str();
		String timestamp = create_timestamp();
		String string1;
		String signature = "";

		// 注意这里参数名必须全部小写，且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}

		ret.put("url", url);
		ret.put("jsapi_ticket", jsapi_ticket);
		ret.put("nonceStr", nonce_str);
		ret.put("timestamp", timestamp);
		ret.put("signature", signature);

		return ret;
	}

	/**
	 * 获取微信公众号js票据
	 * 
	 * @param jsToken
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public String getJSTikect(String jsToken) {
		String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + jsToken + "&type=jsapi";
		LOG.error("jsTicket url:" + url);
		String result = getResponse(url);
		LOG.error("jsTicket:" + result);

		Map<String, Object> data = (Map<String, Object>) JSONUtil.toMap(result);
		if (data == null)
			return null;
		return (String) data.get("ticket");
	}

	/**
	 * 获取网络请求结果
	 * 
	 * @param url
	 * @return
	 */
	protected static String getResponse(String url) {
		try {
			HttpClient client = HttpClientBuilder.create().build();

			HttpGet get = new HttpGet(url);

			HttpResponse response = client.execute(get);
			if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == 200) {
				String result = EntityUtils.toString(response.getEntity(), "UTF-8");

				return result;
			}

			return null;
		} catch (Exception e) {
			// ..
			return null;
		}
	}

	/**
	 * 获取公众号的二维码
	 * 
	 * @param response
	 */
	@RequestMapping("get_code")
	public void getCode(HttpServletResponse response) {
		Shop shop = shopService.queryById(MemberHelper.getShopId());

		response.setCharacterEncoding("utf-8");
		response.setContentType("image/jpeg");

		OutputStream output = null;
		InputStream input = null;
		try {
			String url = shop.getQrCodeUrl();
			URLConnection connect = new URL(url).openConnection();

			input = connect.getInputStream();

			if (input == null)
				return;
			output = response.getOutputStream();
			response.setHeader("Content-Disposition",
					"attachment;filename=" + new String("二维码.jpg".getBytes("UTF-8"), "ISO-8859-1"));
			FileCopyUtils.copy(input, output);

			output.flush();
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		} finally {
			if (output != null) {
				try {
					output.close();
				} catch (IOException e) {
					// ...
				}
			}

			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					// ...
				}
			}
		}
	}

	private static String byteToHex(final byte[] hash) {
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}

	private static String create_nonce_str() {
		return UUID.randomUUID().toString();
	}

	private static String create_timestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}
}
